package first.group.ssh.packet;

import first.group.ssh.SSHConsts;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;

public abstract class PacketParser<T extends Packet> {

    public static boolean bufferRemains(ByteBuffer buffer, int size) {
        return buffer.remaining() >= size;
    }

    public abstract T parse(ByteBuffer buffer) throws IOException;

    private static Map<Integer, PacketParser<? extends Packet>> parsers = null;

    public static Map<Integer, PacketParser<? extends Packet>> getParsers() {
        if (parsers == null) {
            parsers = Map.ofEntries(
                    Map.entry(SSHConsts.SSH_MSG_DISCONNECT, DisconnectPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_IGNORE, IgnorePacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_UNIMPLEMENTED, UnimplementedPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_DEBUG, DebugPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_SERVICE_REQUEST, ServiceRequestPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_SERVICE_ACCEPT, ServiceAcceptPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_KEXINIT, KeyExchangeInitPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_NEWKEYS, NewKeysPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_KEX_DH_GEX_GROUP, DiffieHellmanGroupExchangeGroupPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_KEX_DH_GEX_REPLY, DiffieHellmanGroupExchangeReplyPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_USERAUTH_FAILURE, UserAuthFailurePacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_USERAUTH_SUCCESS, UserAuthSuccessPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_USERAUTH_BANNER, UserAuthBanner.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_GLOBAL_REQUEST, GlobalRequestPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_OPEN, ChannelOpenPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, ChannelOpenComfirmationPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_OPEN_FAILURE, ChannelOpenFailurePacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_WINDOW_ADJUST, ChannelWindowAdjustPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_DATA, ChannelDataPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_EXTENDED_DATA, ChannelExtendedDataPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_EOF, ChannelEofPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_CLOSE, ChannelClosePacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_REQUEST, ChannelRequestPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_SUCCESS, ChannelSuccessPacket.PARSER),
                    Map.entry(SSHConsts.SSH_MSG_CHANNEL_FAILURE, ChannelFailurePacket.PARSER)
            );
        }
        return parsers;
    }
    
    public static PacketParser<? extends Packet> getParserFor(int type) {
        return getParsers().get(type);
    }
}
